import ErrorLog, { ErrorLogDocument } from '../models/errorLogModel';
import { DatabaseError } from '../types/errors';
import { ErrorSeverity } from '../types/audit';
import { logger } from '../utils/logger';

interface ErrorLogSearchParams {
  startDate?: Date;
  endDate?: Date;
  level?: 'ERROR' | 'WARN' | 'INFO';
  code?: string;
  severity?: ErrorSeverity;
  userId?: string;
  page?: number;
  limit?: number;
}

interface SearchResult {
  logs: ErrorLogDocument[];
  total: number;
  page: number;
  totalPages: number;
}

interface ErrorStats {
  totalCount: number;
  bySeverity: {
    [key in ErrorSeverity]: number;
  };
  byLevel: {
    ERROR: number;
    WARN: number;
    INFO: number;
  };
  byCode: Record<string, number>;
}

interface AggregateResult {
  _id: string;
  count: number;
}

export class ErrorLogService {
  /**
   * 记录错误日志
   */
  static async logError(error: Error | unknown, metadata?: any): Promise<ErrorLogDocument> {
    try {
      const errorDetails = error instanceof Error ? {
        name: error.name,
        message: error.message,
        stack: process.env.NODE_ENV === 'development' ? error.stack : undefined,
        code: (error as any).code || 'INTERNAL_ERROR'
      } : {
        name: 'UnknownError',
        message: String(error),
        code: 'INTERNAL_ERROR'
      };

      const entry = new ErrorLog({
        timestamp: new Date(),
        level: 'ERROR',
        ...errorDetails,
        severity: metadata?.severity || ErrorSeverity.HIGH,
        metadata: metadata
      });

      await entry.save();
      return entry;
    } catch (err) {
      logger.error('Failed to create error log:', err);
      throw new DatabaseError('Error log creation failed', { 
        cause: err instanceof Error ? err : new Error(String(err))
      });
    }
  }

  /**
   * 搜索错误日志
   */
  static async searchLogs(params: ErrorLogSearchParams): Promise<SearchResult> {
    try {
      const query: any = {};

      if (params.startDate) {
        query.timestamp = { $gte: params.startDate };
      }
      if (params.endDate) {
        query.timestamp = { ...query.timestamp, $lte: params.endDate };
      }
      if (params.level) {
        query.level = params.level;
      }
      if (params.code) {
        query.code = params.code;
      }
      if (params.severity) {
        query.severity = params.severity;
      }
      if (params.userId) {
        query['metadata.userId'] = params.userId;
      }

      const page = params.page || 1;
      const limit = params.limit || 20;
      const skip = (page - 1) * limit;

      const [logs, total] = await Promise.all([
        ErrorLog.find(query)
          .sort({ timestamp: -1 })
          .skip(skip)
          .limit(limit),
        ErrorLog.countDocuments(query)
      ]);

      return {
        logs,
        total,
        page,
        totalPages: Math.ceil(total / limit)
      };
    } catch (err) {
      throw new DatabaseError('Error log search failed', { 
        cause: err instanceof Error ? err : new Error(String(err))
      });
    }
  }

  /**
   * 获取错误统计信息
   */
  static async getStats(startDate?: Date, endDate?: Date): Promise<ErrorStats> {
    try {
      const query: any = {};
      if (startDate || endDate) {
        query.timestamp = {};
        if (startDate) query.timestamp.$gte = startDate;
        if (endDate) query.timestamp.$lte = endDate;
      }

      const [
        totalCount,
        severityCounts,
        levelCounts,
        codeCounts
      ] = await Promise.all([
        ErrorLog.countDocuments(query),
        ErrorLog.aggregate<AggregateResult>([
          { $match: query },
          { $group: { _id: '$severity', count: { $sum: 1 } } }
        ]),
        ErrorLog.aggregate<AggregateResult>([
          { $match: query },
          { $group: { _id: '$level', count: { $sum: 1 } } }
        ]),
        ErrorLog.aggregate<AggregateResult>([
          { $match: query },
          { $group: { _id: '$code', count: { $sum: 1 } } }
        ])
      ]);

      return {
        totalCount,
        bySeverity: severityCounts.reduce((acc: any, { _id, count }) => {
          acc[_id] = count;
          return acc;
        }, {
          [ErrorSeverity.LOW]: 0,
          [ErrorSeverity.MEDIUM]: 0,
          [ErrorSeverity.HIGH]: 0,
          [ErrorSeverity.CRITICAL]: 0
        }),
        byLevel: levelCounts.reduce((acc: any, { _id, count }) => {
          acc[_id] = count;
          return acc;
        }, {
          ERROR: 0,
          WARN: 0,
          INFO: 0
        }),
        byCode: codeCounts.reduce((acc: any, { _id, count }) => {
          acc[_id] = count;
          return acc;
        }, {})
      };
    } catch (err) {
      throw new DatabaseError('Error stats retrieval failed', { 
        cause: err instanceof Error ? err : new Error(String(err))
      });
    }
  }

  /**
   * 清理过期错误日志
   */
  static async cleanupOldLogs(
    daysToKeep: number = 30,
    excludeSeverities: ErrorSeverity[] = [ErrorSeverity.CRITICAL]
  ): Promise<number> {
    try {
      const cutoffDate = new Date();
      cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);

      const result = await ErrorLog.deleteMany({
        timestamp: { $lt: cutoffDate },
        severity: { $nin: excludeSeverities }
      });

      logger.info(`Cleaned up ${result.deletedCount} old error logs`);
      return result.deletedCount;
    } catch (err) {
      throw new DatabaseError('Error log cleanup failed', { 
        cause: err instanceof Error ? err : new Error(String(err))
      });
    }
  }
}
